{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. 在测试视频(OpenCV安装目录\\sources\\samples\\data)上，使用基于混合高斯模型的背景提取算法，提取前景并显示(显示二值化图像，前景为白色)。\n",
    "答：代码如下"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "import cv2\n",
    "\n",
    "cap = cv2.VideoCapture(r'vtest.avi')\n",
    "fgbg = cv2.createBackgroundSubtractorMOG2()\n",
    "thresh = 200\n",
    "\n",
    "count = 0\n",
    "frame_cnt = 0\n",
    "flag = 1\n",
    "while True:\n",
    "    frame_cnt += 1\n",
    "    ret, frame = cap.read()\n",
    "    if not ret:\n",
    "        break\n",
    "    # 获得前景眼膜\n",
    "    fgmask = fgbg.apply(frame)\n",
    "    # 降噪\n",
    "    _, fgmask = cv2.threshold(fgmask, 30, 0xff, cv2.THRESH_BINARY)\n",
    "\n",
    "    bgImage = fgbg.getBackgroundImage()\n",
    "    cv2.imshow(str(frame_cnt), fgmask)\n",
    "    key = cv2.waitKey(100)\n",
    "    if key == 27:\n",
    "        break;\n",
    "cap.release()\n",
    "cv2.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. 在1基础上，将前景目标进行分割，进一步使用不同颜色矩形框标记，并在命令行窗口中输出每个矩形框的位置和大小。\n",
    "答： 代码如下"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "共检测到 1 个目标 \n",
      "\n",
      "共检测到 3 个目标 \n",
      "\n",
      "共检测到 3 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 3 个目标 \n",
      "\n",
      "共检测到 3 个目标 \n",
      "\n",
      "共检测到 3 个目标 \n",
      "\n",
      "共检测到 3 个目标 \n",
      "\n",
      "共检测到 3 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 3 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 3 个目标 \n",
      "\n",
      "共检测到 3 个目标 \n",
      "\n",
      "共检测到 2 个目标 \n",
      "\n",
      "共检测到 2 个目标 \n",
      "\n",
      "共检测到 2 个目标 \n",
      "\n",
      "共检测到 2 个目标 \n",
      "\n",
      "共检测到 2 个目标 \n",
      "\n",
      "共检测到 2 个目标 \n",
      "\n",
      "共检测到 2 个目标 \n",
      "\n",
      "共检测到 2 个目标 \n",
      "\n",
      "共检测到 2 个目标 \n",
      "\n",
      "共检测到 2 个目标 \n",
      "\n",
      "共检测到 2 个目标 \n",
      "\n",
      "共检测到 3 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 3 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 5 个目标 \n",
      "\n",
      "共检测到 5 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n",
      "共检测到 4 个目标 \n",
      "\n"
     ]
    }
   ],
   "source": [
    "import cv2\n",
    "\n",
    "cap = cv2.VideoCapture(r'vtest.avi')\n",
    "fgbg = cv2.createBackgroundSubtractorMOG2()\n",
    "thresh = 200\n",
    "\n",
    "frame_cnt = 0\n",
    "while True:\n",
    "    frame_cnt += 1\n",
    "    ret, frame = cap.read()\n",
    "    if not ret:\n",
    "        break\n",
    "    # 获得前景眼膜\n",
    "    fgmask = fgbg.apply(frame)\n",
    "    # 降噪\n",
    "    _, fgmask = cv2.threshold(fgmask, 30, 0xff, cv2.THRESH_BINARY)\n",
    "\n",
    "    bgImage = fgbg.getBackgroundImage()\n",
    "    _, cnts, _ = cv2.findContours(fgmask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
    "    # 轮廓数量\n",
    "    count = 0\n",
    "    for c in cnts:\n",
    "        area = cv2.contourArea(c)\n",
    "        if (area < thresh):\n",
    "            continue\n",
    "        count += 1\n",
    "\n",
    "        #画出长方形\n",
    "        x, y, w, h = cv2.boundingRect(c)\n",
    "        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0xff, 0), 2)\n",
    "    print('共检测到', count, '个目标', '\\n')\n",
    "    cv2.imshow('frame', frame)\n",
    "    cv2.imshow('Background', bgImage)\n",
    "\n",
    "    key = cv2.waitKey(100)\n",
    "    if key == 27:\n",
    "        break\n",
    "cap.release()\n",
    "cv2.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. 安装ImageWatch，并在代码中通过设置断点，观察处理中间结果图像。 \n",
    "答：如图\n",
    "![Image text](https://gitee.com/Warren233/w3prince_hao344279065/raw/4a3b74b74755e641f0161d5d7e2febbe47bc4f26/imageWatch%E6%88%AA%E5%9B%BE.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. 使用光流估计方法，在前述测试视频上计算特征点，进一步进行特征点光流估计。 \n",
    "答： 代码如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "import cv2\n",
    "\n",
    "#角点检测参数\n",
    "feature_params = dict(maxCorners = 100, # 取特征最明显的100个特征点\n",
    "                      qualityLevel = 0.01, # harris角点检测响应函数的值\n",
    "                      minDistance = 0.7, # 特征点之间最小的距离\n",
    "                      blockSize = 7 # 过滤领域为7内考虑角点检测\n",
    "                     )\n",
    "\n",
    "# lucas kanade 光流法参数\n",
    "lk_params = dict( winSize = (15, 15), # 邻域窗口大小,\n",
    "                maxLevel = 2, # 金字塔层数 -1\n",
    "                criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)# 满足迭代10次或者误差在0.03时停止\n",
    "                )\n",
    "cap = cv2.VideoCapture(r'vtest.avi')\n",
    "\n",
    "#计算第一帧特征点\n",
    "ret, prev = cap.read()\n",
    "prevGray = cv2.cvtColor(prev, cv2.COLOR_BGR2GRAY)\n",
    "p0 = cv2.goodFeaturesToTrack(prevGray, mask = None, **feature_params)\n",
    "\n",
    "while True:\n",
    "    ret, frame = cap.read()\n",
    "    if not ret:\n",
    "        break\n",
    "    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)\n",
    "    \n",
    "    # 计算光流\n",
    "    p1, st, err = cv2.calcOpticalFlowPyrLK(prevGray, gray, p0, None, **lk_params)\n",
    "    \n",
    "    #选取好的跟踪点\n",
    "    goodPoints = p1[st==1]\n",
    "    goodPrevPoints = p0[st==1]\n",
    "    \n",
    "    #在结果图像中叠加画出特征点和计算出来的光流向量\n",
    "    res = frame.copy()\n",
    "    drawColor = (0,0,255)\n",
    "    for i, (cur, prev) in enumerate(zip(goodPoints, goodPrevPoints)):\n",
    "        x0, y0 = cur.ravel()\n",
    "        x1, y1 = prev.ravel()\n",
    "        cv2.line(res,(x0, y0),(x1, y1), (0, 255, 0))\n",
    "        cv2.circle(res, (x0, y0), 3, drawColor)\n",
    "    \n",
    "    #更新上一帧\n",
    "    prevGray = gray.copy()\n",
    "    p0 = goodPoints.reshape(-1, 1, 2)\n",
    "    \n",
    "    #显示计算结果图像\n",
    "    cv2.imshow('检测结果', res)\n",
    "    \n",
    "    key = cv2.waitKey(30)\n",
    "    if key == 27:\n",
    "        break\n",
    "        \n",
    "cap.release()\n",
    "cv2.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
